#include "StdAfx.h"
#include "WorkSchedulingLogic.h"

WorkSchedulingLogic::WorkSchedulingLogic()
: m_bShouldTakeBreak(false)
, m_bCompensateForIdleThreshold(true)
, m_state(STATE_STOPPED)
{
	m_breakDetector.SetIdleThreshold(2*60*1000); //2 minutes of inactivity means break
}

WorkSchedulingLogic::~WorkSchedulingLogic()
{
}

void WorkSchedulingLogic::SetMaxWorkTime(CTimeSpan &workTimeSpan)
{
	m_maxWorkTimeSpan = workTimeSpan;
}

void WorkSchedulingLogic::StartWork()
{
	StopWork();
	m_lstWorkCycles.push_front(WorkCycle());
	m_state = STATE_WORKING;
}

void WorkSchedulingLogic::StopWork()
{
	PauseWork();
	m_state = STATE_STOPPED;
}

void WorkSchedulingLogic::PauseWork()
{
	if (m_lstWorkCycles.empty())
		return;

	WorkCycle &currentCycle = m_lstWorkCycles.front();
	EndWorkCycle(currentCycle);

	m_bShouldTakeBreak = false;
}

WorkSchedulingLogic::eWorkState WorkSchedulingLogic::GetState()
{
	if (m_state == STATE_STOPPED || m_lstWorkCycles.empty())
		return STATE_STOPPED;

	WorkCycle &currentCycle = m_lstWorkCycles.front();
	return (currentCycle.IsFinished() ? STATE_ON_BREAK : STATE_WORKING);
}

void WorkSchedulingLogic::Tick()
{
	eWorkState workState = GetState();
	switch(workState)
	{
	case STATE_WORKING:
		{
			bool bIsOnBreak = m_breakDetector.IsOnBreak();
			if (bIsOnBreak)
			{
				PauseWork();
			}
			else if (!m_bShouldTakeBreak)
			{
				WorkCycle &currentCycle = m_lstWorkCycles.front();
				CTimeSpan elapsedWorkTimeSpan = CTime::GetCurrentTime() - currentCycle.m_startTime;
				m_bShouldTakeBreak = (elapsedWorkTimeSpan > m_maxWorkTimeSpan);
			}

			break;
		}

	case STATE_ON_BREAK:
		{
			if (!m_breakDetector.IsOnBreak())
				StartWork();
			break;
		}
	};
}

CTimeSpan WorkSchedulingLogic::TimeTillBreak()
{
	eWorkState workState = GetState();
	ASSERT(workState == STATE_WORKING);
	if (workState != STATE_WORKING)
		return CTimeSpan();

	WorkCycle &currentCycle = m_lstWorkCycles.front();
	CTimeSpan elapsedWorkTimeSpan = CTime::GetCurrentTime() - currentCycle.m_startTime;
	return m_maxWorkTimeSpan - elapsedWorkTimeSpan;
}

std::list<WorkCycle> WorkSchedulingLogic::GetWorkCycles()
{
	return m_lstWorkCycles;
}

bool WorkSchedulingLogic::ShouldTakeBreak()
{
	return m_bShouldTakeBreak;
}

void WorkSchedulingLogic::SetIdleThresholdSeconds(int seconds)
{
	m_breakDetector.SetIdleThreshold(seconds * 1000);
}

int WorkSchedulingLogic::GetIdleThreasholdSeconds() const
{
	return m_breakDetector.GetIdleThreshold() / 1000;
}

void WorkSchedulingLogic::EndWorkCycle(WorkCycle& workCycle)
{
	if (workCycle.IsFinished())
		return;

	CTime endTime = CTime::GetCurrentTime();
	if (m_bCompensateForIdleThreshold)
		endTime = endTime - CTimeSpan(0,0,0,GetIdleThreasholdSeconds());

	workCycle.EndCycle(endTime);
}

void WorkSchedulingLogic::SetCompensateForIdleThreshold(bool bCompensate)
{
	m_bCompensateForIdleThreshold = bCompensate;
}

bool WorkSchedulingLogic::GetCompensateForIdleThreshold()
{
	return m_bCompensateForIdleThreshold;
}